// 化学方程式平衡验证工具

import type { Equation } from './equation'

export interface ElementBalance {
  element: string
  leftCount: number
  rightCount: number
  balanced: boolean
}

export interface BalanceCheck {
  balanced: boolean
  elements: ElementBalance[]
  totalElements: number
  balancedElements: number
}

export class BalanceChecker {
  /**
   * 检查方程式的元素平衡情况
   * @param equation 要检查的方程式对象
   * @returns 平衡检查结果
   */
  static checkBalance(equation: Equation): BalanceCheck {
    try {
      const elements = this.getAllElementsFromEquation(equation)
      const elementBalances: ElementBalance[] = []

      for (const element of elements) {
        const leftCount = this.getLeftElementCount(equation, element)
        const rightCount = this.getRightElementCount(equation, element)
        const balanced = leftCount === rightCount

        elementBalances.push({
          element,
          leftCount,
          rightCount,
          balanced
        })
      }

      const balancedElements = elementBalances.filter(eb => eb.balanced).length
      const totalElements = elementBalances.length
      const balanced = balancedElements === totalElements && totalElements > 0

      return {
        balanced,
        elements: elementBalances,
        totalElements,
        balancedElements
      }
    } catch (error) {
      console.error('检查平衡时出错:', error)
      return {
        balanced: false,
        elements: [],
        totalElements: 0,
        balancedElements: 0
      }
    }
  }

  /**
   * 从方程式字符串中提取所有元素
   * @param equationStr 方程式字符串
   * @returns 元素数组
   */
  static extractElementsFromString(equationStr: string): string[] {
    const elements = new Set<string>()
    
    // 使用正则表达式匹配化学元素符号（大写字母开头，可能跟小写字母）
    const elementRegex = /[A-Z][a-z]*/g
    const matches = equationStr.match(elementRegex)
    
    if (matches) {
      matches.forEach(element => {
        // 过滤掉一些常见的非元素单词
        if (!this.isNonElement(element)) {
          elements.add(element)
        }
      })
    }
    
    return Array.from(elements)
  }

  /**
   * 检查是否为非化学元素的单词
   * @param word 要检查的单词
   * @returns 是否为非元素
   */
  private static isNonElement(word: string): boolean {
    const nonElements = ['SO', 'NO', 'PO', 'CO'] // 这些通常是分子基团的一部分
    return nonElements.includes(word)
  }

  /**
   * 从方程式对象中获取所有元素（这是一个简化的实现）
   * @param equation 方程式对象
   * @returns 元素数组
   */
  private static getAllElementsFromEquation(equation: Equation): string[] {
    // 由于我们无法直接访问方程式对象的内部结构，
    // 我们从方程式的字符串表示中提取元素
    const equationStr = equation.print()
    return this.extractElementsFromString(equationStr)
  }

  /**
   * 获取左边特定元素的总数（简化实现）
   * @param equation 方程式对象
   * @param element 元素符号
   * @returns 元素数量
   */
  private static getLeftElementCount(equation: Equation, element: string): number {
    // 这里需要实际的方程式对象支持
    // 目前返回0作为占位符
    return 0
  }

  /**
   * 获取右边特定元素的总数（简化实现）
   * @param equation 方程式对象
   * @param element 元素符号
   * @returns 元素数量
   */
  private static getRightElementCount(equation: Equation, element: string): number {
    // 这里需要实际的方程式对象支持
    // 目前返回0作为占位符
    return 0
  }

  /**
   * 从分子式字符串中计算特定元素的数量
   * @param formulaStr 分子式字符串
   * @param element 要计算的元素
   * @returns 元素数量
   */
  static countElementInFormula(formulaStr: string, element: string): number {
    let count = 0
    let i = 0
    
    while (i < formulaStr.length) {
      // 查找元素
      if (formulaStr.substring(i).startsWith(element)) {
        i += element.length
        
        // 查找紧跟的数字
        let numStr = ''
        while (i < formulaStr.length && /\d/.test(formulaStr[i])) {
          numStr += formulaStr[i]
          i++
        }
        
        const num = numStr ? parseInt(numStr, 10) : 1
        count += num
      } else {
        i++
      }
    }
    
    return count
  }

  /**
   * 解析带系数的化合物列表并计算元素总数
   * @param compoundsStr 化合物字符串（如 "2H2SO4 + 3NaOH"）
   * @param element 要计算的元素
   * @returns 元素总数
   */
  static countElementInCompounds(compoundsStr: string, element: string): number {
    let totalCount = 0
    
    // 分割化合物（用+分隔）
    const compounds = compoundsStr.split('+').map(s => s.trim())
    
    for (const compound of compounds) {
      if (!compound) continue
      
      // 提取系数和分子式
      const match = compound.match(/^(\d*)(.+)/)
      if (match) {
        const coefficient = match[1] ? parseInt(match[1], 10) : 1
        const formula = match[2]
        
        const elementCount = this.countElementInFormula(formula, element)
        totalCount += coefficient * elementCount
      }
    }
    
    return totalCount
  }
}